Skip to content

Conversation

@LimKangHyun
Copy link
Collaborator

@LimKangHyun LimKangHyun commented Jul 26, 2025

🛰️ Issue Number

Closes #108

🪐 작업 내용

Redisson 라이브러리 사용

Redisson은 기본적으로 다양한 분산락 구현 기능이 제공되어 해당 라이브러리를 사용해 구현했습니다. 또한, AOP로 분산락을 구현해 여러 서비스의 메서드에 선언적으로 표현할 수 있도록 했습니다. 어노테이션을 사용하는 경우, 코드 중복도 줄고 의도나 가독성에 유리하다고 생각됩니다.

분산락 키 해시태그 사용

lock:room:{roomId}

  • 해시태그 {}를 붙이면 해시태그 안의 값으로만 해시값을 계산해 노드에 할당하기 때문에,
    특정 roomId와 관련된 추가적인 키를 생성할 때 확장성을 고려해, 같은 roomId끼리 같은 슬롯에 저장되도록, 해시태그를 붙였습니다.
  • roomId의 경우도 {%s}로 타입을 지정해놓았는데, 숫자의 경우에도 %s는 숫자의 타입에 관계없이 .toString()을 사용해서 출력하므로 %d보다 안정성이 높다고 생각했습니다.

gameStart와 handlePlayerReady 동시성 문제 해결

스크린샷 2025-07-26 오후 10 33 34
  • 락 적용 전에는 gameStarthandlePlayerReady가 동시에 접근할 경우
    위와 같이 gameStart가 모든 플레이어의 준비상태를 true로 읽고 나서, handlePlayerReady가 실행되어 플레이어의 준비상태가 false가 되어있는 것을 볼 수 있습니다.
    gameStarthandlePlayerReady가 겹치지 않기 위해서는 모든 플레이어의 상태를 읽는 gameStart때문에 roomId에 락을 획득하도록 했습니다. 또한, gameStart에 걸려있는 락과 동일한 락을 사용해야 의미가 있어 handlePlayerReady에도 roomId로 락을 획득하도록 했습니다.
  • 기본적으로 락 대기 시간은 5초, 락 점유 시간은 3초 이지만, gameStart의 경우, 요청 이후에 들어오는 handlePlayerReady요청에 대해서는 즉시 실패시키도록 waitTime을 0으로 설정했습니다.

락 관련 에러코드 추가 (CommonErrorCode)

LOCK_ACQUISITION_FAILED("E409003", HttpStatus.CONFLICT, "다른 요청이 작업 중입니다. 잠시 후 다시 시도해주세요.");

위와 같이 락 획득에 실패하는 경우, 락 획득 실패 예외처리를 추가했습니다. 인터럽트 예외의 경우는 Java에서 InterruptedExcetpion로 스레드 관련 예외로 표준화 되어있어 따로 커스텀예외를 추가하지 않았습니다.

📚 Reference

아래는 분산락 구현 시, 참고한 사이트입니다.
https://helloworld.kurly.com/blog/distributed-redisson-lock/#3-분산락을-보다-손쉽게-사용할-수는-없을까
https://redisson.pro/docs/configuration/#single-mode

✅ Check List

  • 코드가 정상적으로 컴파일되나요?
  • 테스트 코드를 통과했나요?
  • merge할 브랜치의 위치를 확인했나요?
  • Label을 지정했나요?

LimKangHyun and others added 12 commits July 26, 2025 21:30
- gameStart 중 플레이어 준비 상태 변경 방지
- 플레이어 준비 중 gameStart가 읽기 방지
- 락 획득 성공/실패 케이스 테스트
- 인터럽트 예외 처리 테스트
- 락 해제 조건 검증
- 메서드 실행 중 예외 시 락 해제 정상 동작 확인
- SpEL 기반 동적 락 키 생성 검증
- 멀티스레드에서 하나의 스레드만 락 획득 성공하는지 확인
- 단일 스레드 락 획득 정상 동작 테스트
- 서로 다른 키로 락 사용 시 동시 실행 가능 여부 검증
- gameStart와 handlePlayerReady 메서드 간 동일 roomId 락 충돌 테스트
- 테스트용 서비스 클래스 추가
@LimKangHyun LimKangHyun self-assigned this Jul 26, 2025
@LimKangHyun LimKangHyun added the enhancement New feature or request label Jul 26, 2025
@LimKangHyun LimKangHyun linked an issue Jul 26, 2025 that may be closed by this pull request
timerService.startTimer(room, START_DELAY);

PlayerListResponse playerListResponse = toPlayerListResponse(room);
log.info(playerListResponse.toString());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

디버깅용 로그인가요 ㅎㅎ

Copy link
Collaborator Author

@LimKangHyun LimKangHyun Jul 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 gameStart에 락을 안걸었을 때, gameStart가 플레이어의 레디를 전부 읽고나서, handlePlayerReady가 동작해서 실제로 false인 상태로 게임이 시작되는지 보려고 적어놨었습니다!
지금은 필요없을것 같은데 로그 정리해서 커밋해 놓았습니다!

Copy link
Collaborator

@jiwon1217 jiwon1217 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다 !

Copy link
Collaborator

@sehee123 sehee123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

멋져요.. 👍

수고하셨습니다!

Copy link
Collaborator

@silver-eunjoo silver-eunjoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

와.. 어려우셨을 텐데 대단하십니다.. ! 확인했습니다. 고생하셨어요!!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[L5-참고의견]
테스트 코드에 Order는 어떤 이유에서 넣으신 건가요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

서로 테스트간 의존성은 없긴한데 성공, 인터럽트, 실패 순으로 나눠놨습니다!

@LimKangHyun LimKangHyun merged commit 7174f8e into dev Jul 29, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feat] gameStart와 playerReady 사이의 동시성 제어 추가

6 participants